package com.longma.server.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.longma.server.config.ServerConfig;
import com.longma.server.dao.SysUserDAO;
import com.longma.server.pojo.dto.LoginParamDTO;
import com.longma.server.constant.enums.ResponseCode;
import com.longma.server.entity.SysUser;
import com.longma.server.exception.BusinessException;
import com.longma.server.pojo.dto.*;
import com.longma.server.security.JwtTokenUtil;
import com.longma.server.service.ISysUserService;
import com.longma.server.util.AuthContextUtil;
import com.longma.server.util.MybatisPlusPageUtil;
import com.longma.server.util.WrappersUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author HAIBO
 * @since 2021-04-28
 */
@Service
public class SysUserServiceImpl implements  ISysUserService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private ServerConfig serverConfig;

    @Autowired
    private SysUserDAO sysUserDAO;

    /**
     * 用户登录
     */
    @Override
    public String login(LoginParamDTO loginParamDTO) {
        SysUser user = sysUserDAO.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName, loginParamDTO.getUsername()));
        if (user==null){
            throw new BusinessException(ResponseCode.USER_ACCOUNT_NOT_EXIST);
        }
        if(!passwordEncoder.matches(loginParamDTO.getPassword(), user.getPassword())){
            throw new BusinessException(ResponseCode.USER_CREDENTIALS_ERROR);
        }
        return JwtTokenUtil.generateToken(user.getId().toString()
                , user.getLoginName(), user.getType().getValue());

    }

    /**
     *  获取websocket地址
     */
    @Override
    public String getWebSocketUrl() {
        return serverConfig.getWebSocketUrl();
    }

    /**
     * 新增用户
     */
    @Override
    public SysUser addUser(SysUserAddDTO addRequestDTO) {
        if (sysUserDAO.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName, addRequestDTO.getLoginName())) != null){
            throw new BusinessException(ResponseCode.USER_ACCOUNT_ALREADY_EXIST);
        }

        String password = addRequestDTO.getPassword();
        addRequestDTO.setPassword(passwordEncoder.encode(password));

        // 构建实体
        SysUser sysUser  = new SysUser();
        BeanUtil.copyProperties(addRequestDTO,sysUser);

        sysUserDAO.save(sysUser);
        sysUser.setPassword(null);
        return sysUser;
    }

    /**
     * 根据用户id删除用户
     */
    @Override
    public boolean deleteUser(Integer id) {
        return deleteUserByIds(Arrays.asList(id));
    }

    /**
     * 根据用户id列表批量删除用户
     */
    @Override
    public boolean deleteUserByIds(List<Integer> ids) {
        if (!isExistIds(ids)){
            throw new BusinessException(ResponseCode.PARAM_NOT_VALID.setMessage("id不存在"));
        }

        //获取登录用户id
        SysUser cur = sysUserDAO.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName,AuthContextUtil.getLoginName()));
        if(ids.contains(cur.getId())){
            throw new BusinessException(ResponseCode.PARAM_NOT_VALID.setMessage("无法删除自己"));
        }

        return sysUserDAO.removeByIds(ids);
    }

    /**
     * 更新登录用户
     */
    @Override
    public SysUser updateMe(SysUserSelfUpdateDTO updateRequestDTO) {
        SysUser curUser = sysUserDAO.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName, AuthContextUtil.getLoginName()));

        //用户名是否可用
        if(sysUserDAO.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName, updateRequestDTO.getLoginName()).ne(SysUser::getId,curUser.getId()))>0 ) {
            throw new BusinessException(ResponseCode.USER_ACCOUNT_ALREADY_EXIST);
        }

        BeanUtil.copyProperties(updateRequestDTO,curUser);
        sysUserDAO.updateById(curUser);
        curUser.setPassword(null);
        return curUser;
    }

    /**
     * 根据id更新用户
     */
    @Override
    public SysUser updateUser(SysUserUpdateDTO updateRequestDTO) {
        //用户名是否可用
        if(sysUserDAO.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName, updateRequestDTO.getLoginName()).ne(SysUser::getId, updateRequestDTO.getId()))>0 ) {
            throw new BusinessException(ResponseCode.USER_ACCOUNT_ALREADY_EXIST);
        }

        SysUser user = new SysUser();
        BeanUtil.copyProperties(updateRequestDTO,user);
        sysUserDAO.updateById(user);
        user.setPassword(null);
        return user;
    }

    /**
     * 修改登录用户密码用户
     */
    @Override
    public SysUser changePassword(SysUserPasswordUpdateDTO passwordDTO) {
        // 原始密码
        String oldPassword = passwordDTO.getOldPassword();
        SysUser curUser = sysUserDAO.getOne( Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName, AuthContextUtil.getLoginName()));
        if(!passwordEncoder.matches(oldPassword, curUser.getPassword())){
            throw new BusinessException(ResponseCode.USER_CREDENTIALS_ERROR);
        }

        if (passwordDTO.getOldPassword().equals(passwordDTO.getNewPassword())){
            throw new BusinessException(ResponseCode.PARAM_NOT_VALID.setMessage("新密码与旧密码一样"));
        }

        curUser.setPassword(passwordEncoder.encode(passwordDTO.getNewPassword()));

        sysUserDAO.updateById(curUser);
        curUser.setPassword(null);
        return curUser;
    }

    /**
     * 根据登录账号获取用户
     */
    @Override
    public SysUser getUser(String loginName) {
        return sysUserDAO.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName,loginName)).setPassword(null);
    }


    /**
     * 分页查询 获取用户列表
     */
    @Override
    public IPage<SysUser> getByPage(Long pageNum, Long pageSize, Boolean all, List<AdvanceQueryConditionDTO> conditions) {
        //构建查询条件
        LambdaQueryWrapper<SysUser> wrapper = WrappersUtil.lambdaQuery(conditions, SysUser.class);
        Page<SysUser> pageUser = MybatisPlusPageUtil.getPage(pageNum, pageSize, all);
        for(SysUser user:pageUser.getRecords()){
            user.setPassword(null);
        }

        return sysUserDAO.page(pageUser, wrapper);
    }


    /**
     * 登录名是否存在
     */
    @Override
    public boolean checkUsername(String username) {
        return sysUserDAO.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getLoginName,username)) != null;
    }

    @Override
    public boolean checkUserRealName(String realname) {
        return sysUserDAO.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getRealName,realname)) != null;
    }

    private boolean isExistIds(List<Integer> ids) {
        if (CollUtil.isEmpty(ids)) {
            return false;
        }

        //构建查询条件
        LambdaQueryWrapper<SysUser> wrapper = Wrappers.lambdaQuery();

        //转换为set
        Set<Integer> productIds = new HashSet<>(ids);

        //查询是否存在
        return sysUserDAO.count(wrapper.in(SysUser::getId, productIds)) == productIds.size();
    }

}
